package com.ruoyi.system.service.impl;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.Assessment;
import com.ruoyi.system.domain.vo.ScheduleVo;
import com.ruoyi.system.domain.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.Schedule;
import com.ruoyi.system.domain.bo.AttendanceBo;
import com.ruoyi.system.domain.bo.PoliceOfficerBo;
import com.ruoyi.system.domain.bo.ShiftBo;
import com.ruoyi.system.mapper.ScheduleMapper;
import com.ruoyi.system.service.IAttendanceService;
import com.ruoyi.system.service.IPoliceOfficerService;
import com.ruoyi.system.service.IScheduleService;
import com.ruoyi.system.service.IShiftService;
import com.ruoyi.system.service.ScheduleNotificationService;

/**
 * 排班管理Service业务层处理
 *
 * @author ruoyi
 */
@Service
public class ScheduleServiceImpl implements IScheduleService {

    @Autowired
    private ScheduleMapper baseMapper;

    @Autowired
    private IPoliceOfficerService policeOfficerService;

    @Autowired
    private IShiftService shiftService;

    @Autowired
    private IAttendanceService attendanceService;

    @Autowired
    private ScheduleNotificationService notificationService;

    @Override
    public List<Schedule> queryScheduleList(Schedule schedule) {
        return baseMapper.queryScheduleList(schedule);
    }

    /**
     * 查询排班信息列表
     *
     * @param schedule 排班信息
     * @return 排班信息
     */
    @Override
    public List<Schedule> selectScheduleList(Schedule schedule) {
//        // 获取查询参数
//        String startDate = schedule.getStartDate();
//        String endDate = schedule.getEndDate();
//
//        // 如果未指定日期，则默认查询本周数据
//        if (startDate == null || endDate == null) {
//            // 默认显示当前日期一周的数据
//            Calendar cal = Calendar.getInstance();
//
//            // 调整到本周一
//            int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1; // 星期日是1，需要转换
//            if (dayOfWeek == 0) dayOfWeek = 7; // 如果是星期日，设为7
//            cal.add(Calendar.DAY_OF_MONTH, -(dayOfWeek - 1)); // 调整到周一
//
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//            startDate = sdf.format(cal.getTime());
//
//            // 本周日
//            cal.add(Calendar.DAY_OF_MONTH, 6);
//            endDate = sdf.format(cal.getTime());
//
//            // 更新查询参数
//            schedule.setStartDate(startDate);
//            schedule.setEndDate(endDate);
//        }
//
//        // 使用现有服务获取警员列表
//        PoliceOfficerBo policeOfficerBo = new PoliceOfficerBo();
//        policeOfficerBo.setDepartment(schedule.getDepartment());
//        List<PoliceOfficerVo> officers = policeOfficerService.queryList(policeOfficerBo);
//
//        // 使用现有服务获取考勤数据
//        AttendanceBo attendanceBo = new AttendanceBo();
//        List<AttendanceVo> attendances = attendanceService.queryList(attendanceBo);
//
//        // 过滤指定日期范围内的考勤数据
//        List<AttendanceVo> filteredAttendances = new ArrayList<>();
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        try {
//            Date startDateTime = sdf.parse(startDate);
//            Date endDateTime = sdf.parse(endDate);
//
//            for (AttendanceVo attendance : attendances) {
//                Date dutyDate = attendance.getDutyDate();
//                if (dutyDate != null &&
//                    !dutyDate.before(startDateTime) &&
//                    !dutyDate.after(endDateTime)) {
//                    filteredAttendances.add(attendance);
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        // 构建排班信息
//        List<Schedule> scheduleList = new ArrayList<>();
//
//        // 解析日期范围
//        List<Date> dateRange = getDateRange(startDate, endDate);
//
//        // 为每个警员构建排班数据
//        for (PoliceOfficerVo officer : officers) {
//            Schedule officerSchedule = new Schedule();
//            officerSchedule.setOfficerId(officer.getId());
//            officerSchedule.setOfficerName(officer.getName());
//            officerSchedule.setOfficerType(officer.getPostType());
//            officerSchedule.setDepartment(officer.getDepartment());
//
//            // 构建该警员的排班明细
//            Map<String, Object> scheduleDetails = new HashMap<>();
//            int totalHours = 0;
//            int totalShifts = 0;
//
//            // 遍历日期范围
//            for (Date date : dateRange) {
//                String dateStr = sdf.format(date);
//
//                // 在考勤数据中查找该警员在该日期的排班
//                AttendanceVo dayAttendance = findOfficerAttendance(filteredAttendances,
//                        officer.getId(), dateStr);
//
//                if (dayAttendance != null) {
//                    // 如果有排班数据
//                    Map<String, Object> daySchedule = new HashMap<>();
//                    daySchedule.put("shiftId", null);
//                    daySchedule.put("shiftName", dayAttendance.getShiftName());
//                    daySchedule.put("timePeriod", dayAttendance.getShiftTimePeriod());
//
//                    scheduleDetails.put(dateStr, daySchedule);
//
//                    // 计算工作时长（如果不是休息）
//                    if (!"休息".equals(dayAttendance.getShiftName())) {
//                        totalShifts++;
//                        // 计算工作时长
//                        String timePeriod = dayAttendance.getShiftTimePeriod();
//                        if (!"全天".equals(timePeriod)) {
//                            totalHours += calculateHours(timePeriod);
//                        }
//                    }
//                } else {
//                    // 如果没有排班数据，标记为未排班
//                    Map<String, Object> emptySchedule = new HashMap<>();
//                    emptySchedule.put("shiftId", null);
//                    emptySchedule.put("shiftName", "未排班");
//                    emptySchedule.put("timePeriod", "");
//                    scheduleDetails.put(dateStr, emptySchedule);
//                }
//            }
//
//            officerSchedule.setSchedule(scheduleDetails);
//
//            scheduleList.add(officerSchedule);
//        }

        return null;
    }

    /**
     * 获取推荐的算法参数
     *
     * @return 算法参数
     */
    @Override
    public Map<String, Object> getRecommendedAlgorithmParams() {
        // 根据历史数据和规则推荐算法参数
        Map<String, Object> params = new HashMap<>();
        params.put("maxConsecutiveWorkDays", 5);
        params.put("maxWorkDaysPerWeek", 5);
        params.put("minRestHours", 12);
        params.put("demandFactor", 1.0);
        params.put("fairnessWeight", 0.7);
        params.put("skillMatchWeight", 0.3);
        params.put("considerHistoricalData", true);
        params.put("considerOfficerPreferences", true);
        return params;
    }

    /**
     * 批量保存排班信息
     *
     * @param scheduleList 排班信息列表
     * @return 结果
     */
    @Override
    public boolean batchSaveSchedule(List<Schedule> scheduleList) {
        if (scheduleList == null || scheduleList.isEmpty()) {
            return false;
        }

        try {
            // 保存排班信息
            boolean result = baseMapper.insertBatch(scheduleList);

            if (result) {
                // 发送排班通知消息
                for (Schedule schedule : scheduleList) {
                    notificationService.sendScheduleCreateNotification(
                        schedule.getOfficerId(),
                        schedule.getOfficerName(),
                        schedule.getShiftName(),
                        schedule.getScheduleDate()
                    );
                }
            }

            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据日期范围删除排班信息
     *
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 结果
     */
    @Override
    public boolean deleteScheduleByDateRange(String startDate, String endDate) {
        try {
            // 删除排班信息
            int rows = baseMapper.deleteScheduleByDateRange(startDate, endDate);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public TableDataInfo<ScheduleVo> queryDutyDetails(Schedule schedule, PageQuery pageQuery) {
        LambdaQueryWrapper<Schedule> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(schedule.getOfficerName()), Schedule::getOfficerName, schedule.getOfficerName())
            .like(StringUtils.isNotBlank(schedule.getDutyType()), Schedule::getDutyType, schedule.getDutyType())
            .like(StringUtils.isNotBlank(schedule.getPoints()), Schedule::getPoints, schedule.getPoints())
            .like(StringUtils.isNotBlank(schedule.getRoute()), Schedule::getRoute, schedule.getRoute())
            .orderByDesc(Schedule::getCreateTime);

        Page<ScheduleVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 生成智能排班
     *
     * @param params 排班参数
     * @return 结果
     */
    @Override
    public boolean generateSchedule(Map<String, Object> params) {
        try {
            // 1. 获取算法参数
            Map<String, Object> algorithmParams = (Map<String, Object>) params.get("algorithmParams");

            // 2. 获取排班日期范围
            String startDate = (String) params.get("startDate");
            String endDate = (String) params.get("endDate");

            // 3. 获取部门和警员类型
            String department = params.get("department") != null ? params.get("department").toString() : null;
            String officerType = params.get("officerType") != null ? params.get("officerType").toString() : null;

            // 4. 先删除该日期范围内的原有排班
            deleteScheduleByDateRange(startDate, endDate);

            // 5. 获取警员和班次数据
            PoliceOfficerBo policeOfficerBo = new PoliceOfficerBo();
            if (department != null) {
                policeOfficerBo.setDepartment(department);
            }
            if (officerType != null) {
                policeOfficerBo.setPostType(officerType);
            }
            List<PoliceOfficerVo> officers = policeOfficerService.queryList(policeOfficerBo);

            ShiftBo shiftBo = new ShiftBo();
            List<ShiftVo> shifts = shiftService.queryList(shiftBo);

            // 6. 执行排班算法
            List<Schedule> schedules = executeSchedulingAlgorithm(officers, shifts, startDate, endDate, algorithmParams);

            // 7. 保存排班结果
            return batchSaveSchedule(schedules);

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 调整排班
     *
     * @param params 调整参数
     * @return 结果
     */
    @Override
    public boolean adjustSchedule(Map<String, Object> params) {
        try {
            // 获取调整信息
            Long officerId = Long.parseLong(params.get("officerId").toString());
            String dateStr = (String) params.get("dateStr");
            Long shiftId = params.get("shiftId") != null ? Long.parseLong(params.get("shiftId").toString()) : null;
            String reason = (String) params.get("reason");

            // 转换日期字符串为Date
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            // 查询是否已存在该警员当天的排班
            Schedule existingSchedule = baseMapper.selectScheduleByOfficerAndDate(officerId, dateStr);

            if (existingSchedule != null) {
                // 更新已存在的排班
                if (shiftId != null && !shiftId.equals(existingSchedule.getShiftId())) {
                    // 获取班次信息
                    ShiftVo shift = shiftService.queryById(shiftId);
                    if (shift != null) {
                        existingSchedule.setShiftId(shift.getId());
                        existingSchedule.setShiftName(shift.getShiftName());
                        existingSchedule.setTimePeriod(shift.getShiftTimePeriod());
                    }
                }

                // 设置调整信息
                existingSchedule.setIsAdjusted(1); // 标记为已调整
                existingSchedule.setUpdateTime(new Date());

                // 更新排班
                List<Schedule> updateList = new ArrayList<>();
                return baseMapper.updateById(existingSchedule) > 0;
            } else {
                // 新增排班记录
                Schedule newSchedule = new Schedule();
                newSchedule.setOfficerId(officerId);

                // 获取警员信息
                PoliceOfficerVo officer = policeOfficerService.queryById(officerId);
                if (officer != null) {
                    newSchedule.setOfficerName(officer.getName());
                    newSchedule.setOfficerType(officer.getPostType());
                    newSchedule.setDepartment(officer.getDepartment());
                }

                // 设置排班日期
                try {
                    newSchedule.setScheduleDate(sdf.parse(dateStr));
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }

                // 获取班次信息
                if (shiftId != null) {
                    ShiftVo shift = shiftService.queryById(shiftId);
                    if (shift != null) {
                        newSchedule.setShiftId(shift.getId());
                        newSchedule.setShiftName(shift.getShiftName());
                        newSchedule.setTimePeriod(shift.getShiftTimePeriod());
                    }
                }

                // 设置调整信息
                newSchedule.setIsAdjusted(1); // 标记为已调整
                newSchedule.setCreateTime(new Date());
                newSchedule.setUpdateTime(new Date());

                // 添加排班
                List<Schedule> insertList = new ArrayList<>();
                insertList.add(newSchedule);
                return batchSaveSchedule(insertList);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取警员出勤统计
     *
     * @param officerId 警员ID
     * @return 出勤统计数据
     */
    @Override
    public Map<String, Object> selectOfficerAttendanceStats(Long officerId) {
        Map<String, Object> result = new HashMap<>();

        // 获取基础信息
        Map<String, Object> officerStats = baseMapper.selectOfficerStats(officerId);
        if (officerStats == null) {
            officerStats = new HashMap<>();
        }

        // 获取警员班次分布
        List<Map<String, Object>> shiftDistribution = baseMapper.selectOfficerShiftDistribution(officerId);
        if (shiftDistribution == null) {
            shiftDistribution = new ArrayList<>();
        }

        // 获取警员月度工时历史
        List<Map<String, Object>> monthlyWorkHours = baseMapper.selectOfficerMonthlyWorkHours(officerId);
        if (monthlyWorkHours == null) {
            monthlyWorkHours = new ArrayList<>();
        }

        // 获取警员考核历史
        List<Map<String, Object>> assessmentHistory = baseMapper.selectOfficerAssessmentHistory(officerId);
        if (assessmentHistory == null) {
            assessmentHistory = new ArrayList<>();
        }

        // 构建返回结果
        Map<String, Object> stats = new HashMap<>();
        stats.put("monthHours", officerStats.get("monthHours"));
        stats.put("nightShifts", officerStats.get("nightShifts"));
        stats.put("restDays", officerStats.get("restDays"));
        stats.put("shiftDistribution", shiftDistribution);
        stats.put("monthlyWorkHours", monthlyWorkHours);

        result.put("officerId", officerStats.get("officerId"));
        result.put("officerName", officerStats.get("officerName"));
        result.put("department", officerStats.get("department"));
        result.put("officerType", officerStats.get("officerType"));
        result.put("officerAvatar", officerStats.get("officerAvatar"));
        result.put("stats", stats);
        result.put("assessment", assessmentHistory);

        return result;
    }

    /**
     * 在考勤数据中查找特定警员在特定日期的排班
     */
    private AttendanceVo findOfficerAttendance(List<AttendanceVo> attendances, Long officerId, String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        for (AttendanceVo attendance : attendances) {
            if (officerId.equals(attendance.getScheduledOfficerId())) {
                String attDateStr = sdf.format(attendance.getDutyDate());
                if (dateStr.equals(attDateStr)) {
                    return attendance;
                }
            }
        }
        return null;
    }

    /**
     * 计算班次工作时长
     */
    private int calculateHours(String timePeriod) {
        if (timePeriod == null || "全天".equals(timePeriod)) {
            return 0;
        }

        try {
            String[] times = timePeriod.split("-");
            int startHour = Integer.parseInt(times[0].split(":")[0]);
            int endHour = Integer.parseInt(times[1].split(":")[0]);

            // 处理跨日的情况
            if (endHour < startHour) {
                return (24 - startHour) + endHour;
            } else {
                return endHour - startHour;
            }
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 获取日期范围
     */
    private List<Date> getDateRange(String startDateStr, String endDateStr) {
        List<Date> dateRange = new ArrayList<>();
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date startDate = sdf.parse(startDateStr);
            Date endDate = sdf.parse(endDateStr);

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);

            while (!calendar.getTime().after(endDate)) {
                dateRange.add(calendar.getTime());
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dateRange;
    }

    /**
     * 执行排班算法
     */
    private List<Schedule> executeSchedulingAlgorithm(List<PoliceOfficerVo> officers, List<ShiftVo> shifts,
            String startDateStr, String endDateStr, Map<String, Object> params) {
        List<Schedule> result = new ArrayList<>();

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date startDate = sdf.parse(startDateStr);
            Date endDate = sdf.parse(endDateStr);

            // 记录工作日期数
            List<Date> dateRange = getDateRange(startDateStr, endDateStr);

            // 为每个警员生成排班
            for (PoliceOfficerVo officer : officers) {
                int consecutiveWorkDays = 0; // 连续工作天数

                // 遍历日期范围
                for (Date date : dateRange) {
                    // 创建新的排班记录
                    Schedule schedule = new Schedule();
                    schedule.setOfficerId(officer.getId());
                    schedule.setOfficerName(officer.getName());
                    schedule.setOfficerType(officer.getPostType());
                    schedule.setDepartment(officer.getDepartment());
                    schedule.setScheduleDate(date);
                    schedule.setIsAdjusted(0); // 未调整

                    // 获取适合的班次
                    ShiftVo shift;

                    // 如果连续工作5天或以上，安排休息
                    int maxConsecutiveWorkDays = 5; // 默认值
                    if (params.containsKey("maxConsecutiveWorkDays")) {
                        maxConsecutiveWorkDays = Integer.parseInt(params.get("maxConsecutiveWorkDays").toString());
                    }

                    if (consecutiveWorkDays >= maxConsecutiveWorkDays) {
                        shift = getRestShift(shifts);
                        consecutiveWorkDays = 0; // 重置连续工作天数
                    } else {
                        shift = getRandomWorkShift(shifts);
                        consecutiveWorkDays++;
                    }

                    // 设置班次信息
                    if (shift != null) {
                        schedule.setShiftId(shift.getId());
                        schedule.setShiftName(shift.getShiftName());
                        schedule.setTimePeriod(shift.getShiftTimePeriod());
                    }

                    result.add(schedule);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 获取休息班次
     */
    private ShiftVo getRestShift(List<ShiftVo> shifts) {
        for (ShiftVo shift : shifts) {
            if ("休息".equals(shift.getShiftName())) {
                return shift;
            }
        }
        // 如果没有休息班次，返回第一个
        return shifts.isEmpty() ? null : shifts.get(0);
    }

    /**
     * 获取随机工作班次（排除休息）
     */
    private ShiftVo getRandomWorkShift(List<ShiftVo> shifts) {
        List<ShiftVo> workShifts = new ArrayList<>();
        for (ShiftVo shift : shifts) {
            if (!"休息".equals(shift.getShiftName())) {
                workShifts.add(shift);
            }
        }

        if (workShifts.isEmpty()) {
            return shifts.isEmpty() ? null : shifts.get(0);
        }

        int randomIndex = (int) (Math.random() * workShifts.size());
        return workShifts.get(randomIndex);
    }

    @Override
    public boolean personAdjust(Schedule schedule) {
        return baseMapper.updateById(schedule) > 0;
    }

    @Override
    public boolean delete(Long id) {
        return baseMapper.deleteById(id) > 0;
    }
}
